﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.LIB;
using YArchitech.Revit;

namespace YArchitech.Plumbing
{
	public class PlumbSystemAutoDesign
	{
		public PlumbSystemAutoDesign(Document curDoc)
		{
			this.doc = curDoc;
		}

		public PlumbSystemAutoDesign(UIDocument uiD)
		{
			this.Uidoc = uiD;
			this.doc = uiD.Document;
		}

		public PlumbSystemAutoDesign(Document curDoc, Wall baseWall, IList<Element> elemSet)
		{
			this.wall = baseWall;
			this.listElem = elemSet;
			this.doc = curDoc;
			this.ExamineDesignRule();
		}

		public string ExamineInfo
		{
			get
			{
				return this.examineInfo;
			}
		}

		private void ExamineDesignRule()
		{
			this.examineInfo = this.ExamineElements();
			if (this.examineInfo != "")
			{
				return;
			}
			this.examineInfo = this.ExamineFamilyInstanceSite();
            //this.examineInfo != "";
		}

		private string ExamineElements()
		{
			if (this.listElem == null || this.listElem.Count <= 0)
			{
				return "没有选中任何实体，请重新选择设备……";
			}
			foreach (Element element in this.listElem)
			{
				if (element is Pipe)
				{
					this.riserPipe = (element as Pipe);
				}
				if (element is FamilyInstance)
				{
					ConnectorManager connectorManager = (element as FamilyInstance).MEPModel.ConnectorManager;
					if (connectorManager != null)
					{
						ConnectorSet connectors = connectorManager.Connectors;
						if (connectors != null && connectors.Size > 0)
						{
							ConnectorSetIterator connectorSetIterator = connectors.ForwardIterator();
							int num = 0;
							while (connectorSetIterator.MoveNext())
							{
								object obj = connectorSetIterator.Current;
								Connector connector = obj as Connector;
								if (connector != null && 3 == (int)connector.Domain && (int)connector.Direction == 2)
								{
									num++;
								}
							}
							if (num > 0)
							{
								this.listFamilyInstance.Add(element as FamilyInstance);
							}
						}
					}
				}
			}
			if (this.riserPipe == null)
			{
				return "选择实体集合中必须包含一个水管立管，\n请重新选择设计用实体集合……";
			}
			if (this.listFamilyInstance.Count <= 0)
			{
				return "选择实体集合中至少包含一个卫生设备，\n请重新选择设计用实体集合……";
			}
			return "";
		}

		private void GetWallLine()
		{
			LocationCurve locationCurve = this.wall.Location as LocationCurve;
			this.wallStartPnt = locationCurve.Curve.GetEndPoint(0);
			this.wallStartPnt = new XYZ(this.wallStartPnt.X, this.wallStartPnt.Y, 0.0);
			this.wallEndPnt = locationCurve.Curve.GetEndPoint(1);
			this.wallEndPnt = new XYZ(this.wallEndPnt.X, this.wallEndPnt.Y, 0.0);
			this.wallVector = this.wallEndPnt.Subtract(this.wallStartPnt).Normalize();
			this.wallLine = this.doc.CreatYJKLine(this.wallStartPnt, this.wallVector, false);
		}

		private XYZ GetFamilyPoint(FamilyInstance fi)
		{
			XYZ point = (fi.Location as LocationPoint).Point;
			return new XYZ(point.X, point.Y, 0.0);
		}

		private void GetPipeStartPoint()
		{
			XYZ hyendPoint = (this.riserPipe.Location as LocationCurve).Curve.GetEndPoint(0);
			this.pipePoint = new XYZ(hyendPoint.X, hyendPoint.Y, 0.0);
			this.pipeLine = this.doc.CreatYJKLine(this.pipePoint, this.wallVector, false);
		}

		private XYZ GetFPointInWallLine(XYZ point)
		{
			return this.wallLine.Project(point).XYZPoint;
		}

		private XYZ GetProjectPoint(Line line, XYZ point)
		{
			return line.Project(point).XYZPoint;
		}

		private string ExamineFamilyInstanceSite()
		{
			this.GetWallLine();
			this.GetPipeStartPoint();
			int num = 0;
			XYZ xyz = null;
			if (this.listFamilyInstance.Count <= 1)
			{
				return "";
			}
			foreach (FamilyInstance fi in this.listFamilyInstance)
			{
				XYZ familyPoint = this.GetFamilyPoint(fi);
				XYZ projectPoint = this.GetProjectPoint(this.pipeLine, familyPoint);
				XYZ xyz2 = familyPoint.Subtract(this.pipePoint).Subtract(familyPoint.Subtract(projectPoint)).Normalize();
				if (num == 0)
				{
					xyz = xyz2;
					num++;
				}
				else if (!xyz2.IsAlmostEqualTo(xyz))
				{
					return "选择器具必须在立管的同一侧，\n请重新选择操作实体……";
				}
			}
			return "";
		}

		private XYZ GetSanitaryConnPoint(FamilyInstance fi)
		{
			Connector elementOutConnector = YJKRevitTools.GetElementOutConnector(fi, (Autodesk.Revit.DB.Domain)3);
			return new XYZ(elementOutConnector.Origin.X, elementOutConnector.Origin.Y, 0.0);
		}

		private double GetMaxDisToWallFamily()
		{
			double num = 0.0;
			foreach (FamilyInstance fi in this.listFamilyInstance)
			{
				double sanitaryToWallDis = this.GetSanitaryToWallDis(fi);
				if (sanitaryToWallDis >= num)
				{
					num = sanitaryToWallDis;
				}
			}
			return num;
		}

		private double GetSanitaryToWallDis(FamilyInstance fi)
		{
			return this.wallLine.Distance(this.GetSanitaryConnPoint(fi));
		}

		private double GetActiveViewLevelOffset()
		{
			return this.doc.ActiveView.GenLevel.Elevation;
		}

		private double GetActiveViewLevel()
		{
			return this.doc.ActiveView.GenLevel.Elevation * 304.8;
		}

		private void OrderFamilyInstance()
		{
			foreach (FamilyInstance familyInstance in this.listFamilyInstance)
			{
				this.dicFamily.Add(familyInstance, this.pipePoint.DistanceTo(this.GetFamilyPoint(familyInstance)));
			}
			this.dicFamily = (from r in this.dicFamily
			orderby r.Value descending
			select r).ToDictionary((KeyValuePair<FamilyInstance, double> r) => r.Key, (KeyValuePair<FamilyInstance, double> r) => r.Value);
		}

		private PipingSystemType GetPipingSystemType()
		{
			PipingSystem pipingSystem = this.riserPipe.MEPSystem as PipingSystem;
			return this.doc.GetElementById(pipingSystem.GetTypeId()) as PipingSystemType;
		}

		private Pipe GetNextConnPipe(List<Pipe> listPipe)
		{
			Pipe result = null;
			if (listPipe.Count <= 0)
			{
				return result;
			}
			if (listPipe.Count == 1)
			{
				return listPipe[0];
			}
			if (listPipe.Count != 2)
			{
				return result;
			}
			IList<XYZ> elementEndPoint = YJKRevitTools.GetElementEndPoint(listPipe[0]);
			IList<XYZ> elementEndPoint2 = YJKRevitTools.GetElementEndPoint(listPipe[1]);
			XYZ xyz = elementEndPoint[0].Add(elementEndPoint[1]) / 2.0;
			XYZ xyz2 = elementEndPoint2[0].Add(elementEndPoint2[1]) / 2.0;
			double num = YJKRevitTools.DistanceTwoXYZ(xyz, this.pipePoint);
			double num2 = YJKRevitTools.DistanceTwoXYZ(xyz2, this.pipePoint);
			if (num < num2)
			{
				return listPipe[0];
			}
			return listPipe[1];
		}

		private bool SetViewPlanDepth(double offset)
		{
			ViewPlan viewPlan = this.doc.ActiveView as Autodesk.Revit.DB.ViewPlan;
			return viewPlan != null && UnifiedModified.SetViewBottomDepth(viewPlan, offset);
		}

		private Pipe CreatStandardPipe(double distanceToWall, double offset, double diameter, double slope)
		{
			XYZ projectPoint = this.GetProjectPoint(this.wallLine, this.pipePoint);
			this.OrderFamilyInstance();
			FamilyInstance fi = this.dicFamily.Keys.First<FamilyInstance>();
			XYZ projectPoint2 = this.GetProjectPoint(this.wallLine, this.GetFamilyPoint(fi));
			double offset2 = this.GetMaxDisToWallFamily() * 304.8 + distanceToWall;
			HYCreatePipeHelper hycreatePipeHelper = new HYCreatePipeHelper();
			PipeType pipeType = this.riserPipe.PipeType;
			PipingSystemType pipingSystemType = this.GetPipingSystemType();
			return hycreatePipeHelper.DrawThwartwisePipe(this.doc, offset2, offset, projectPoint, projectPoint2, pipeType, diameter, pipingSystemType, slope, this.pipePoint);
		}

		public void FamilysConnToPipe()
		{
			double offset = this.GetActiveViewLevel() - 500.0;
			SubTransaction subTransaction = new SubTransaction(this.doc);
			subTransaction.Start();
			Pipe pipe = this.CreatStandardPipe(600.0, offset, 100.0, 0.012);
			subTransaction.Commit();
			try
			{
				AutoDesignHelper autoDesignHelper = new AutoDesignHelper();
				string text = "";
				List<Pipe> list = new List<Pipe>();
				int num = 0;
				foreach (KeyValuePair<FamilyInstance, double> keyValuePair in this.dicFamily)
				{
					if (num == 0)
					{
						list = autoDesignHelper.PipeConnectEquipment(keyValuePair.Key, pipe, ref text);
						num++;
					}
					else if (list.Count > 0)
					{
						pipe = this.GetNextConnPipe(list);
						list = autoDesignHelper.PipeConnectEquipment(keyValuePair.Key, pipe, ref text);
					}
				}
				this.GetNextConnPipe(list);
				new YJKPipeConnectorHelper();
			}
			catch (Exception)
			{
				throw;
			}
			this.SetViewPlanDepth(-550.0);
		}

		public double GetLineToXAngle(XYZ startPnt, XYZ endPnt)
		{
			double num = 0.0;
			XYZ xyz = new XYZ(startPnt.X, startPnt.Y, 0.0);
			XYZ xyz2 = new XYZ(endPnt.X, endPnt.Y, 0.0).Subtract(xyz).Normalize();
			if (Math.Abs(xyz2.X) < 0.0001)
			{
				if (xyz2.Y > 0.0)
				{
					num = 90.0;
				}
				if (xyz2.Y < 0.0)
				{
					num = 270.0;
				}
				if (xyz2.Y == 0.0)
				{
					num = 0.0;
				}
			}
			if (Math.Abs(xyz2.Y) < 0.0001)
			{
				if (xyz2.X == 0.0)
				{
					num = 0.0;
				}
				if (xyz2.X > 0.0)
				{
					num = 0.0;
				}
				if (xyz2.X < 0.0)
				{
					num = 180.0;
				}
			}
			if ((xyz2.X > 0.0 && xyz2.Y > 0.0) || (xyz2.X < 0.0 && xyz2.Y > 0.0))
			{
				num = Convert.ToDouble(StringTools.CutOffEfficacious((new XYZ(1.0, 0.0, 0.0).AngleTo(xyz2) * 180.0 / Math.PI).ToString(), 2));
			}
			if ((xyz2.X > 0.0 && xyz2.Y < 0.0) || (xyz2.X < 0.0 && xyz2.Y < 0.0))
			{
				num = new XYZ(1.0, 0.0, 0.0).AngleTo(xyz2) * 180.0 / Math.PI;
				num = Convert.ToDouble(StringTools.CutOffEfficacious((360.0 - num).ToString(), 2));
			}
			if (num == 360.0)
			{
				num = 0.0;
			}
			return num;
		}

		public XYZ GetPipeLineVector(double angle)
		{
			XYZ xyz = new XYZ(1.0, 0.0, 0.0);
			XYZ xyz2 = new XYZ(0.0, 1.0, 0.0);
			double num = 0.001;
			double num2 = angle * 180.0 / Math.PI;
			XYZ result;
			if (Math.Abs(num2) < num)
			{
				result = xyz;
			}
			else if (Math.Abs(num2 - 90.0) < num)
			{
				result = xyz2;
			}
			else if (Math.Abs(num2 - 180.0) < num)
			{
				result = xyz * -1.0;
			}
			else if (Math.Abs(num2 - 270.0) < num)
			{
				result = xyz2 * -1.0;
			}
			else if (Math.Abs(num2 - 360.0) < num)
			{
				result = xyz;
			}
			else if (num2 >= num && num2 <= 90.0 - num)
			{
				result = xyz + xyz2 * Math.Tan(angle);
			}
			else if (num2 >= 90.0 + num && num2 <= 180.0 - num)
			{
				result = xyz * -1.0 + xyz2 * Math.Tan(Math.PI - angle);
			}
			else if (num2 >= 180.0 + num && num2 <= 270.0 - num)
			{
				result = xyz * -1.0 + -1.0 * xyz2 * Math.Tan(angle - Math.PI);
			}
			else if (num2 >= 270.0 + num && num2 <= 360.0 - num)
			{
				result = xyz + -1.0 * xyz2 * Math.Tan(Math.PI*2 - angle);
			}
			else
			{
				result = null;
			}
			return result;
		}

		public double GetElevation(Document doc, double pipeOffset)
		{
			return doc.ActiveView.GenLevel.Elevation + pipeOffset / 304.8;
		}

		private XYZ GetPipeStartPnt(Pipe pipe, double zValue)
		{
			XYZ result = null;
			if (YJKRevitTools.isRiserPipe(pipe))
			{
				XYZ xyz = YJKRevitTools.GetElementEndPoint(pipe)[0];
				result = new XYZ(xyz.X, xyz.Y, zValue);
			}
			return result;
		}

		private XYZ GetPipeStartPnt(Pipe pipe, FamilyInstance fi)
		{
			XYZ familyInstancePnt = this.GetFamilyInstancePnt(fi);
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe);
			Connector connector = hypiping.StartConnector.Connector;
			Connector connector2 = hypiping.EndConnector.Connector;
			XYZ origin = connector.Origin;
			XYZ origin2 = connector2.Origin;
			XYZ result;
			if (connector.IsConnected)
			{
				result = connector2.Origin;
			}
			else if (connector2.IsConnected)
			{
				result = connector.Origin;
			}
			else
			{
				result = ((familyInstancePnt.DistanceTo(origin) > familyInstancePnt.DistanceTo(origin2)) ? origin2 : origin);
			}
			return result;
		}

		private XYZ GetFarthestPoint(List<FamilyInstance> listFI, XYZ startPnt, XYZ vector, double zValue)
		{
			XYZ xyz = null;
			YJKLine hyline = new YJKLine(startPnt, startPnt + vector);
			hyline.MakeUnBound();
			double num = 0.0;
			foreach (FamilyInstance fi in listFI)
			{
				XYZ familyInstancePnt = this.GetFamilyInstancePnt(fi, zValue);
				if (familyInstancePnt != null)
				{
					XYZ project = hyline.GetProject(familyInstancePnt);
					if (project.DistanceTo(startPnt) > num)
					{
						xyz = project;
						num = project.DistanceTo(startPnt);
					}
				}
			}
			if (xyz == null)
			{
				return xyz;
			}
			XYZ xyz2 = xyz.Subtract(startPnt).Normalize();
			xyz = xyz.Subtract(xyz2 * 20.0 / 304.8);
			return xyz;
		}

		private XYZ GetFamilyInstancePnt(FamilyInstance fi, double zValue)
		{
			XYZ result = null;
			Connector elementOutConnector = YJKRevitTools.GetElementOutConnector(fi, (Autodesk.Revit.DB.Domain)3);
			if (elementOutConnector == null)
			{
				return result;
			}
			XYZ xyz = elementOutConnector.Origin;
			if (fi.Document.IsLinked)
			{
				xyz = this.doc.GetLinkedDocument(fi.Id).GetPointInLinkDocument(xyz);
			}
			return new XYZ(xyz.X, xyz.Y, zValue);
		}

		public XYZ GetFamilyInstancePnt(FamilyInstance fi)
		{
			XYZ xyz = (fi.Location as LocationPoint).Point;
			if (fi.Document.IsLinked)
			{
				xyz = this.doc.GetLinkedDocument(fi.Id).GetPointInLinkDocument(xyz);
			}
			return xyz;
		}

		public PipingSystemType GetPipeSystemType(Pipe pipe)
		{
			return pipe.Document.GetElementById(pipe.GetParameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).AsElementId()) as PipingSystemType;
		}

		public PipeType GetPipeType(Pipe pipe)
		{
			return pipe.PipeType;
		}

		public Pipe CreatHorizontalPipe(Pipe riserPipe, double pipeOffset, List<FamilyInstance> listFI, XYZ vector, double diameter, double slope)
		{
			Document document = riserPipe.Document;
			double elevation = this.GetElevation(document, pipeOffset);
			XYZ xyz = this.GetPipeStartPnt(riserPipe, elevation);
			PipingSystemType pipeSystemType = this.GetPipeSystemType(riserPipe);
			PipeType pipeType = this.GetPipeType(riserPipe);
			XYZ farthestPoint = this.GetFarthestPoint(listFI, xyz, vector, elevation);
			if (farthestPoint == null)
			{
				return null;
			}
			xyz += vector * 6.0 / 304.8;
			return YJKRevitTools.createPipe(0.0, xyz, farthestPoint, diameter, slope, pipeSystemType, pipeType, document);
		}

		public Pipe CheckAndExtendPipe(Pipe riserPipe, double pipeOffset)
		{
			Document document = riserPipe.Document;
			double elevation = this.GetElevation(document, pipeOffset);
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(riserPipe);
			double num = hypiping.GetDiameter() * 3.0;
			XYZ origin = hypiping.StartConnector.Origin;
			XYZ origin2 = hypiping.EndConnector.Origin;
			XYZ xyz;
			XYZ xyz2;
			if (origin.Z > origin2.Z)
			{
				xyz = origin;
				xyz2 = origin2;
			}
			else
			{
				xyz = origin2;
				xyz2 = origin;
			}
			double x = xyz2.X;
			double y = xyz2.Y;
			Pipe pipe;
			if (xyz2.Z >= elevation)
			{
				double num2 = elevation - num;
				pipe = hypiping.Extend(xyz, new XYZ(x, y, num2));
			}
			else if (xyz.Z <= elevation)
			{
				double num2 = elevation + num;
				pipe = hypiping.Extend(new XYZ(x, y, num2), xyz2);
			}
			else
			{
				pipe = riserPipe;
			}
			document.Regenerate();
			new YJKRotateFamilyInstance().MovePiping(pipe);
			return pipe;
		}

		public Pipe CreatHorizontalPipe(Pipe hPipe, XYZ pipePnt, List<FamilyInstance> listFI, XYZ vector, double diameter, double slope)
		{
			Document document = hPipe.Document;
			double z = pipePnt.Z;
			PipingSystemType pipeSystemType = this.GetPipeSystemType(hPipe);
			PipeType pipeType = this.GetPipeType(hPipe);
			XYZ farthestPoint = this.GetFarthestPoint(listFI, pipePnt, vector, z);
			if (farthestPoint == null)
			{
				return null;
			}
			return YJKRevitTools.createPipe(0.0, pipePnt, farthestPoint, diameter, slope, pipeSystemType, pipeType, document);
		}

		public string CheckElements(List<Element> listElem, bool beRiser, bool bSplitFlow)
		{
			if (listElem == null || listElem.Count < 1)
			{
				return "没有选中任何实体，\n请重新选择设备……";
			}
			List<Pipe> list = new List<Pipe>();
			List<FamilyInstance> list2 = new List<FamilyInstance>();
			foreach (Element element in listElem)
			{
				if (element is Pipe)
				{
					this.riserPipe = (element as Pipe);
					list.Add(this.riserPipe);
				}
				if (element is FamilyInstance)
				{
					ConnectorManager connectorManager = (element as FamilyInstance).MEPModel.ConnectorManager;
					if (connectorManager != null)
					{
						ConnectorSet connectors = connectorManager.Connectors;
						if (connectors != null && connectors.Size > 0)
						{
							ConnectorSetIterator connectorSetIterator = connectors.ForwardIterator();
							int num = 0;
							while (connectorSetIterator.MoveNext())
							{
								object obj = connectorSetIterator.Current;
								Connector connector = obj as Connector;
								if (connector != null && 3 == (int)connector.Domain && (int)connector.Direction == 2)
								{
									num++;
								}
							}
							if (num > 0)
							{
								list2.Add(element as FamilyInstance);
							}
						}
					}
				}
			}
			if (list.Count <= 0)
			{
				if (beRiser)
				{
					if (bSplitFlow)
					{
						return "选择实体集合中必须包含两根立管，\n请重新选择设计用实体集合……";
					}
					return "选择实体集合中必须包含一根立管，\n请重新选择设计用实体集合……";
				}
				else
				{
					if (bSplitFlow)
					{
						return "选择实体集合中必须包含两根横管，\n请重新选择设计用实体集合……";
					}
					return "选择实体集合中必须包含一根横管，\n请重新选择设计用实体集合……";
				}
			}
			else if (list.Count != 1 && !bSplitFlow)
			{
				if (beRiser)
				{
					return "选择实体集合中必须是一根立管，\n请重新选择设计用实体集合……";
				}
				return "选择实体集合中必须是一根横管，\n请重新选择设计用实体集合……";
			}
			else if (list.Count != 2 && bSplitFlow)
			{
				if (beRiser)
				{
					return "选择实体集合中必须是两根立管，\n请重新选择设计用实体集合……";
				}
				return "选择实体集合中必须是两根横管，\n请重新选择设计用实体集合……";
			}
			else
			{
				if (beRiser)
				{
					if (bSplitFlow)
					{
						if (!YJKRevitTools.isRiserPipe(list[0]) || !YJKRevitTools.isRiserPipe(list[1]))
						{
							return "选择实体集合中必须是两根立管，\n请重新选择设计用实体集合……";
						}
					}
					else if (!YJKRevitTools.isRiserPipe(list[0]))
					{
						return "选择实体集合中必须是一根立管，\n请重新选择设计用实体集合……";
					}
				}
				if (!beRiser)
				{
					if (bSplitFlow)
					{
						if (YJKRevitTools.isRiserPipe(list[0]) || YJKRevitTools.isRiserPipe(list[1]))
						{
							return "选择实体集合中必须是两根横管，\n请重新选择设计用实体集合……";
						}
					}
					else if (YJKRevitTools.isRiserPipe(list[0]))
					{
						return "选择实体集合中必须是一根横管，\n请重新选择设计用实体集合……";
					}
				}
				if (list.Count == 2)
				{
					Parameter parameter = list[0].GetParameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM);
					Parameter parameter2 = list[1].GetParameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM);
					if (((!parameter.AsValueString().Contains("污水") && !parameter2.AsValueString().Contains("污水")) || (!parameter.AsValueString().Contains("废水") && !parameter2.AsValueString().Contains("废水"))) && (!parameter.AsValueString().Contains("卫生设备") || !parameter2.AsValueString().Contains("卫生设备")))
					{
						return "选择实体集合中必须有一根污水管和一根废水管，\n请重新选择设计用实体集合……";
					}
				}
				if (list2.Count <= 0)
				{
					return "选择实体集合中至少包含一个卫生设备，\n请重新选择设计用实体集合……";
				}
				return "";
			}
		}

		public Pipe ExtendBasePipe(Pipe pipe, List<FamilyInstance> listFI, ref XYZ point)
		{
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe);
			Connector connector = hypiping.StartConnector.Connector;
			Connector connector2 = hypiping.EndConnector.Connector;
			if (connector.IsConnected && connector2.IsConnected)
			{
				return pipe;
			}
			XYZ xyz;
			XYZ xyz2;
			if (connector.IsConnected)
			{
				xyz = connector.Origin;
				xyz2 = this.GetExtendEndPoint(connector.Origin, connector2.Origin, listFI);
			}
			else if (connector2.IsConnected)
			{
				xyz = this.GetExtendEndPoint(connector2.Origin, connector.Origin, listFI);
				xyz2 = connector2.Origin;
			}
			else
			{
				List<XYZ> extendEndPoint = this.GetExtendEndPoint(listFI, connector.Origin, connector2.Origin);
				xyz = extendEndPoint[0];
				xyz2 = extendEndPoint[1];
			}
			Pipe pipe2 = hypiping.Extend(xyz, xyz2);
			new YJKRotateFamilyInstance().MovePiping(pipe2);
			double num = point.DistanceTo(xyz);
			double num2 = point.DistanceTo(xyz2);
			point = ((num < num2) ? xyz : xyz2);
			return pipe2;
		}

		private List<FamilyInstance> OrderIntances(List<FamilyInstance> listFI, YJKLine hyLine)
		{
			List<FamilyInstance> list = new List<FamilyInstance>();
			hyLine.MakeUnBound();
			Dictionary<FamilyInstance, double> dictionary = new Dictionary<FamilyInstance, double>();
			double z = hyLine.StartPoint.Z;
			XYZ xyz = null;
			for (int i = 0; i < listFI.Count; i++)
			{
				if (i == 0)
				{
					dictionary.Add(listFI[i], 0.0);
					xyz = this.GetFamilyInstancePnt(listFI[i], z);
				}
				else
				{
					double value = this.GetFamilyInstancePnt(listFI[i], z).DistanceTo(xyz);
					dictionary.Add(listFI[i], value);
				}
			}
			dictionary = (from r in dictionary
			orderby r.Value
			select r).ToDictionary((KeyValuePair<FamilyInstance, double> r) => r.Key, (KeyValuePair<FamilyInstance, double> r) => r.Value);
			FamilyInstance key = dictionary.Last<KeyValuePair<FamilyInstance, double>>().Key;
			xyz = this.GetFamilyInstancePnt(key, z);
			dictionary = new Dictionary<FamilyInstance, double>();
			foreach (FamilyInstance familyInstance in listFI)
			{
				double value2 = this.GetFamilyInstancePnt(familyInstance, z).DistanceTo(xyz);
				dictionary.Add(familyInstance, value2);
			}
			dictionary = (from r in dictionary
			orderby r.Value
			select r).ToDictionary((KeyValuePair<FamilyInstance, double> r) => r.Key, (KeyValuePair<FamilyInstance, double> r) => r.Value);
			foreach (KeyValuePair<FamilyInstance, double> keyValuePair in dictionary)
			{
				list.Add(keyValuePair.Key);
			}
			return list;
		}

		private void CheckAndExtendLine(XYZ basePnt, ref XYZ startPnt, ref XYZ endPnt, ref YJKLine hyLine, bool firstPntBeExtend = true)
		{
			if (hyLine.IsPointOnLineExtension(basePnt))
			{
				double num = basePnt.DistanceTo(startPnt);
				double num2 = basePnt.DistanceTo(endPnt);
				if (num < num2)
				{
					if (firstPntBeExtend)
					{
						startPnt = basePnt;
					}
				}
				else
				{
					endPnt = basePnt;
				}
				hyLine = new YJKLine(startPnt, endPnt);
				hyLine.MakeUnBound();
			}
		}

		private List<XYZ> GetExtendEndPoint(List<FamilyInstance> listFI, XYZ startPnt, XYZ endPnt)
		{
			List<XYZ> list = new List<XYZ>();
			YJKLine hyline = new YJKLine(startPnt, endPnt);
			hyline.MakeUnBound();
			XYZ item = startPnt;
			XYZ item2 = endPnt;
			List<FamilyInstance> source = this.OrderIntances(listFI, hyline);
			XYZ familyInstancePnt = this.GetFamilyInstancePnt(source.First<FamilyInstance>(), startPnt.Z);
			XYZ project = hyline.GetProject(familyInstancePnt);
			this.CheckAndExtendLine(project, ref item, ref item2, ref hyline, true);
			familyInstancePnt = this.GetFamilyInstancePnt(source.Last<FamilyInstance>(), startPnt.Z);
			project = hyline.GetProject(familyInstancePnt);
			this.CheckAndExtendLine(project, ref item, ref item2, ref hyline, true);
			list.Add(item);
			list.Add(item2);
			return list;
		}

		private XYZ GetExtendEndPoint(XYZ startPnt, XYZ endPnt, List<FamilyInstance> listFI)
		{
			YJKLine hyline = new YJKLine(startPnt, endPnt);
			hyline.MakeUnBound();
			XYZ result = endPnt;
			List<FamilyInstance> source = this.OrderIntances(listFI, hyline);
			XYZ familyInstancePnt = this.GetFamilyInstancePnt(source.First<FamilyInstance>(), startPnt.Z);
			XYZ project = hyline.GetProject(familyInstancePnt);
			this.CheckAndExtendLine(project, ref startPnt, ref result, ref hyline, false);
			familyInstancePnt = this.GetFamilyInstancePnt(source.Last<FamilyInstance>(), startPnt.Z);
			project = hyline.GetProject(familyInstancePnt);
			this.CheckAndExtendLine(project, ref startPnt, ref result, ref hyline, false);
			return result;
		}

		public bool JudgeBeDrawPipe(Pipe pipe, List<FamilyInstance> listFI, ref XYZ point)
		{
			XYZ elementCurve = YJKRevitTools.GetElementCurve(pipe, 0);
			XYZ elementCurve2 = YJKRevitTools.GetElementCurve(pipe, 1);
			this.GetFamilyInstancePnt(listFI[0], 0.0);
			XYZ pipeStartPnt = this.GetPipeStartPnt(pipe, listFI[0]);
			if (listFI.Count == 1)
			{
				point = pipeStartPnt;
				return false;
			}
			Dictionary<FamilyInstance, double> source = this.OrderFamilyInstanceList(listFI, pipeStartPnt);
			pipeStartPnt = this.GetPipeStartPnt(pipe, source.First<KeyValuePair<FamilyInstance, double>>().Key);
			XYZ xyz = elementCurve.IsAlmostEqualTo(pipeStartPnt) ? elementCurve2 : elementCurve;
			xyz = new XYZ(xyz.X, xyz.Y, pipeStartPnt.Z);
			this.GetFamilyInstancePnt(source.First<KeyValuePair<FamilyInstance, double>>().Key, pipeStartPnt.Z);
			this.GetFamilyInstancePnt(source.Last<KeyValuePair<FamilyInstance, double>>().Key, pipeStartPnt.Z);
			XYZ xyz2 = xyz.Subtract(pipeStartPnt).Normalize();
			Connector elementOutConnector = YJKRevitTools.GetElementOutConnector(listFI[0], (Autodesk.Revit.DB.Domain)3);
			XYZ xyz3 = new XYZ();
			LocationPoint locationPoint = listFI[0].Location as LocationPoint;
			if (locationPoint == null)
			{
				point = pipeStartPnt;
				return false;
			}
			xyz3 = ((elementOutConnector == null) ? new XYZ(0.0, 0.0, locationPoint.Point.Z).Normalize() : elementOutConnector.CoordinateSystem.BasisZ);
			XYZ xyz4;
			if (xyz3.IsAlmostEqualTo(new XYZ(0.0, 0.0, -1.0)) || xyz3.IsAlmostEqualTo(new XYZ(0.0, 0.0, 1.0)))
			{
				xyz4 = ((elementOutConnector == null) ? new XYZ(locationPoint.Point.X, 0.0, 0.0).Normalize() : elementOutConnector.CoordinateSystem.BasisX);
			}
			else
			{
				xyz4 = ((elementOutConnector == null) ? new XYZ(0.0, locationPoint.Point.Y, 0.0).Normalize() : elementOutConnector.CoordinateSystem.BasisY);
			}
			double num = xyz4.AngleTo(xyz2) * 180.0 / Math.PI;
			bool result = num >= 30.0 && num <= 150.0;
			point = pipeStartPnt;
			return result;
		}

		public Dictionary<FamilyInstance, double> OrderFamilyInstanceList(List<FamilyInstance> listFI, XYZ pnt)
		{
			new List<FamilyInstance>();
			Dictionary<FamilyInstance, double> dictionary = new Dictionary<FamilyInstance, double>();
			foreach (FamilyInstance familyInstance in listFI)
			{
				XYZ familyInstancePnt = this.GetFamilyInstancePnt(familyInstance);
				dictionary.Add(familyInstance, pnt.DistanceTo(familyInstancePnt));
			}
			dictionary = (from r in dictionary
			orderby r.Value
			select r).ToDictionary((KeyValuePair<FamilyInstance, double> r) => r.Key, (KeyValuePair<FamilyInstance, double> r) => r.Value);
			return dictionary;
		}

		public List<FamilyInstance> orderFamilyInstance(Pipe riserPipe, double pipeOffset, List<FamilyInstance> listFI, ref XYZ sPoint)
		{
			Document document = riserPipe.Document;
			double elevation = this.GetElevation(document, pipeOffset);
			XYZ pipeStartPnt = this.GetPipeStartPnt(riserPipe, elevation);
			sPoint = pipeStartPnt;
			Dictionary<FamilyInstance, double> dictionary = this.OrderFamilyInstanceList(listFI, pipeStartPnt);
			List<FamilyInstance> list = new List<FamilyInstance>();
			foreach (KeyValuePair<FamilyInstance, double> keyValuePair in dictionary)
			{
				list.Add(keyValuePair.Key);
			}
			return list;
		}

		public List<FamilyInstance> orderFamilyInstance(XYZ startPnt, List<FamilyInstance> listFI)
		{
			Dictionary<FamilyInstance, double> dictionary = this.OrderFamilyInstanceList(listFI, startPnt);
			List<FamilyInstance> list = new List<FamilyInstance>();
			foreach (KeyValuePair<FamilyInstance, double> keyValuePair in dictionary)
			{
				list.Add(keyValuePair.Key);
			}
			return list;
		}

		public bool BeConnPipes(Pipe pipe1, Pipe pipe2, XYZ originalPnt, ref XYZ pnt1, ref XYZ pnt2)
		{
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe1);
			YJKPiping<Pipe> hypiping2 = new YJKPiping<Pipe>(pipe2);
			XYZ xyz = new XYZ(originalPnt.X, originalPnt.Y, 0.0);
			XYZ xyz2;
			if (hypiping.StartConnector.Origin.IsAlmostEqualTo(originalPnt))
			{
				pnt1 = hypiping.EndConnector.Origin;
				pnt1 = new XYZ(pnt1.X, pnt1.Y, 0.0);
				xyz2 = pnt1.Subtract(xyz);
			}
			else
			{
				pnt1 = hypiping.StartConnector.Origin;
				pnt1 = new XYZ(pnt1.X, pnt1.Y, 0.0);
				xyz2 = pnt1.Subtract(xyz);
			}
			XYZ xyz3;
			if (hypiping2.StartConnector.Origin.IsAlmostEqualTo(originalPnt))
			{
				pnt2 = hypiping2.EndConnector.Origin;
				pnt2 = new XYZ(pnt2.X, pnt2.Y, 0.0);
				xyz3 = pnt2.Subtract(xyz);
			}
			else
			{
				pnt2 = hypiping2.StartConnector.Origin;
				pnt2 = new XYZ(pnt2.X, pnt2.Y, 0.0);
				xyz3 = pnt2.Subtract(xyz);
			}
			double num = xyz3.AngleTo(xyz2) * 180.0 / Math.PI;
			if (Math.Abs(num - 180.0) < 3.0)
			{
				throw new Exception("新建管道与原有管道不能平行，\n可选择不绘制管道进行连接。");
			}
			return num - 90.0 >= -0.01;
		}

		public string GetAccessoryName(FamilyInstance fi)
		{
			Parameter parameter = fi.GetParameter("HY-AutoConnectType");
			string result;
			if (parameter == null || !parameter.HasValue)
			{
				string name = fi.Symbol.Family.Name;
				if (name.Contains("大便器"))
				{
					result = "大便器";
				}
				else if (name.Contains("小便器"))
				{
					result = "小便器";
				}
				else if (name.Contains("地漏"))
				{
					result = "地漏";
				}
				else if (name.Contains("水盆"))
				{
					result = "水盆";
				}
				else
				{
					result = "其他";
				}
			}
			else
			{
				string text = parameter.AsString();
				if (text.Contains("大便器"))
				{
					result = "大便器";
				}
				else if (text.Contains("小便器"))
				{
					result = "小便器";
				}
				else if (text.Contains("地漏"))
				{
					result = "地漏";
				}
				else if (text.Contains("水盆"))
				{
					result = "水盆";
				}
				else
				{
					result = "其他";
				}
			}
			return result;
		}

		public FamilySymbol GetTeeFamilySymbol(string fsName, Document doc, ref string loadMSG)
		{
			FamilySymbol familySymbol = null;
			if (string.IsNullOrEmpty(fsName))
			{
				loadMSG = "族名不能为空！";
				return familySymbol;
			}
			familySymbol = YJKRevitTools.GetFamilySymbol(fsName, doc);
			if (familySymbol == null)
			{
				string text = Path.Combine(Product.FamilyLocation, RevitVersion.Version, "Fitting", fsName + ".rfa");
				if (!File.Exists(text))
				{
					loadMSG = "族不存在或者加载地址不正确！";
					return familySymbol;
				}
				SubTransaction subTransaction = new SubTransaction(doc);
				subTransaction.Start();
				Family family = null;
				doc.LoadFamily(text, out family);
				if (family == null)
				{
					subTransaction.RollBack();
					return null;
				}
				familySymbol = YJKRevitTools.GetFamilySymbol(fsName, doc);
				subTransaction.Commit();
			}
			return familySymbol;
		}

		public string ValidatingElements(List<Element> listElem, bool beRiser)
		{
			if (listElem == null || listElem.Count < 1)
			{
				return "没有选中任何实体，\n请重新选择设备……";
			}
			List<Pipe> list = new List<Pipe>();
			List<FamilyInstance> list2 = new List<FamilyInstance>();
			foreach (Element element in listElem)
			{
				if (element is Pipe)
				{
					this.riserPipe = (element as Pipe);
					list.Add(this.riserPipe);
				}
				if (element is FamilyInstance)
				{
					list2.Add(element as FamilyInstance);
				}
			}
			if (list.Count <= 0)
			{
				if (beRiser)
				{
					return "选择实体集合中必须包含一根立管，\n请重新选择设计用实体集合……";
				}
				return "选择实体集合中必须包含一根横管，\n请重新选择设计用实体集合……";
			}
			else if (list.Count != 1)
			{
				if (beRiser)
				{
					return "选择实体集合中只能包含一根立管，\n请重新选择设计用实体集合……";
				}
				return "选择实体集合中只能包含一根横管，\n请重新选择设计用实体集合……";
			}
			else
			{
				if (beRiser && !YJKRevitTools.isRiserPipe(list[0]))
				{
					return "选择实体集合中必须是一根立管，\n请重新选择设计用实体集合……";
				}
				if (!beRiser && YJKRevitTools.isRiserPipe(list[0]))
				{
					return "选择实体集合中必须是一根横管，\n请重新选择设计用实体集合……";
				}
				if (list2.Count <= 0)
				{
					return "选择实体集合中至少包含一个卫浴设备，\n请重新选择设计用实体集合……";
				}
				return "";
			}
		}

		public string CheckingElements(List<Element> listElem, bool beRiser, ref Pipe pipeCold, ref Pipe pipeHot)
		{
			if (listElem == null || listElem.Count < 1)
			{
				return "没有选中任何实体，\n请重新选择设备……";
			}
			List<Pipe> list = new List<Pipe>();
			List<FamilyInstance> list2 = new List<FamilyInstance>();
			foreach (Element element in listElem)
			{
				if (element is Pipe)
				{
					this.riserPipe = (element as Pipe);
					list.Add(this.riserPipe);
				}
				if (element is FamilyInstance)
				{
					list2.Add(element as FamilyInstance);
				}
			}
			if (list2.Count <= 0)
			{
				return "选择实体集合中至少包含一个卫浴设备，\n请重新选择设计用实体集合……";
			}
			return this.PipeIdentification(list, ref pipeCold, ref pipeHot, beRiser);
		}

		private string PipeIdentification(List<Pipe> listPipe, ref Pipe pipeCold, ref Pipe pipeHot, bool beRiser)
		{
			List<Pipe> list = new List<Pipe>();
			List<Pipe> list2 = new List<Pipe>();
			foreach (Pipe pipe in listPipe)
			{
				if (beRiser)
				{
					if (YJKRevitTools.isRiserPipe(pipe))
					{
                        if (YJKRevitTools.BePipeSystemType(pipe, (PipeSystemType)20))
						{
							list.Add(pipe);
						}
                        else if (YJKRevitTools.BePipeSystemType(pipe, (PipeSystemType)19))
						{
							list2.Add(pipe);
						}
					}
				}
				else if (!YJKRevitTools.isRiserPipe(pipe))
				{
                    if (YJKRevitTools.BePipeSystemType(pipe, (PipeSystemType)20))
					{
						list.Add(pipe);
					}
                    else if (YJKRevitTools.BePipeSystemType(pipe, (PipeSystemType)19))
					{
						list2.Add(pipe);
					}
				}
			}
			if (list.Count <= 0 && list2.Count <= 0)
			{
				if (beRiser)
				{
					return "选择实体集合中必须包含一根立管，\n请重新选择设计用实体集合……";
				}
				return "选择实体集合中必须包含一根横管，\n请重新选择设计用实体集合……";
			}
			else
			{
				if (list.Count == 1)
				{
					pipeCold = list[0];
				}
				else if (list.Count > 1)
				{
                    pipeCold = this.SelPipe(beRiser, (PipeSystemType)20);
				}
				if (list2.Count == 1)
				{
					pipeHot = list2[0];
				}
				else if (list2.Count > 1)
				{
                    pipeHot = this.SelPipe(beRiser, (PipeSystemType)19);
				}
				if (pipeCold == null && pipeHot == null)
				{
					return "没有选择合适的管道连接到系统";
				}
				return "";
			}
		}

		private Pipe SelPipe(bool beRiser, PipeSystemType sysType)
		{
			Pipe result;
			try
			{
				ISelectionFilter selectionFilter;
				string text;
				if (beRiser)
				{
					selectionFilter = new RiserPipeFilter();
                    if ((int)sysType == 20)
					{
						text = "选择的管道包含多根家用冷水立管，请选择“系统分类为家用冷水”的立管用于连接卫浴";
					}
					else
					{
                        if ((int)sysType != 19)
						{
							return null;
						}
						text = "选择的管道包含多根家用热水立管，请选择“系统分类为家用热水”的立管用于连接卫浴";
					}
				}
				else
				{
					selectionFilter = new HoriPipeFilter();
                    if ((int)sysType == 20)
					{
						text = "选择的管道包含多根家用冷水横管，请选择“系统分类为家用冷水”的横管用于连接卫浴";
					}
					else
					{
                        if ((int)sysType != 19)
						{
							return null;
						}
						text = "选择的管道包含多根家用热水横管，请选择“系统分类为家用热水”的横管用于连接卫浴";
					}
				}
				Reference reference = this.Uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, selectionFilter, text);
				while (!YJKRevitTools.BePipeSystemType(this.doc.GetElement(reference.ElementId) as Pipe, sysType))
				{
					reference = this.Uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, selectionFilter, text);
				}
				result = (this.doc.GetElement(reference.ElementId) as Pipe);
			}
			catch
			{
				result = null;
			}
			return result;
		}

		private Wall wall;

		private IList<Element> listElem;

		private Document doc;

		private UIDocument Uidoc;

		private Pipe riserPipe;

		private IList<FamilyInstance> listFamilyInstance = new List<FamilyInstance>();

		private XYZ wallStartPnt;

		private XYZ wallEndPnt;

		private Line wallLine;

		private XYZ pipePoint;

		private XYZ wallVector;

		private Line pipeLine;

		private string examineInfo;

		private Dictionary<FamilyInstance, double> dicFamily = new Dictionary<FamilyInstance, double>();
	}
}
